import router from "@/router"
import { isEmpty } from "@/utils"
import { defineStore } from "pinia"
import type { LocationQueryRaw, RouteLocationNormalizedGeneric, RouteLocationNormalizedLoaded, RouteMeta } from "vue-router"

export type RouteTag = {
    fullPath: string
    path: string
    name: string
    hash: string
    meta: RouteMeta
    params: object
    query?: LocationQueryRaw
    cacheName?: string
}

export type TabViewCloseMethods = {
    closeTab: (tag: RouteTag) => void
    closeLeftTabs: (tag: RouteTag) => void
    closeRightTabs: (tag: RouteTag) => void
    closeOtherTabs: (tag: RouteTag) => void
    closeAllTabs: () => void
}

/**
 * 多标签页
 */
export const useTabViewStore = defineStore("tabView", () => {
    // 当前标签页
    const activeTab = ref<string>("")
    // 标签页
    const tabs = ref<RouteTag[]>([])
    // 缓存
    const cachedComponents = ref<string[]>([])

    function _buildTag(route: RouteLocationNormalizedLoaded): RouteTag {
        const { fullPath, hash, meta, name, params, path, query } = route
        const tag: RouteTag = { name: name as string, path, fullPath, hash, meta, params, query }
        if (meta.noCache === true) {
            tag.cacheName = undefined
        } else {
            tag.cacheName = route.name as string
        }
        return tag
    }

    /**
     * 判断是否当前路由
     */
    const isActiveTab = (tag: RouteTag) => {
        return tag.fullPath === activeTab.value
    }

    /**
     * 是否固定标签页
     */
    const isAffixTab = (tag: RouteTag) => {
        return tag.meta.affix === true
    }

    /**
     * 返回指定标签的位置
     */
    const _index = (tag: RouteTag) => {
        return tabs.value.findIndex(item => item.fullPath == tag.fullPath)
    }

    /**
     * 自动导航到指定标签页
     */
    const _autoRouter = (tag: RouteTag) => {
        router.push({ path: tag.path, query: tag.query })
    }

    /**
     * 标签状态
     */
    const tabStatus = (tag: RouteTag) => {
        const attr: Recordable<boolean> = {
            canClose: true,
            canCloseLeft: true,
            canCloseRight: true,
            canCloseOthers: true,
            canCloseAll: true
        }
        if (tabs.value.length <= 1) {
            Object.keys(attr).forEach(key => (attr[key] = false))
            return attr
        }
        const index = _index(tag)
        if (index < 0) {
            Object.keys(attr).forEach(key => (attr[key] = false))
            return attr
        }
        if (isAffixTab(tag)) {
            attr.canClose = false
        }
        if (index === 0) {
            attr.canCloseLeft = false
        }
        if (index >= tabs.value.length - 1) {
            attr.canCloseRight = false
        }
        return attr
    }

    /**
     * 根据当前路由新建标签页，缓存由 router 守卫进行添加
     */
    const addTab = (route: RouteLocationNormalizedLoaded) => {
        const exist = tabs.value.some(item => item.fullPath === route.fullPath)
        if (!exist) {
            tabs.value.push(_buildTag(route))
            activeTab.value = route.fullPath
        } else {
            activeTab.value = route.fullPath
        }
    }

    /**
     * 转换标签页
     */
    const changeTab = (key: string) => {
        const tab = tabs.value.find(item => item.fullPath == key)
        tab && _autoRouter(tab)
    }

    /**
     * 关闭菜单
     */
    const closeTab = (tag: RouteTag) => {
        // 固定标签页不能关闭
        if (isAffixTab(tag) || tabs.value.length <= 1) {
            return
        }
        // 获取标签位置
        const index = _index(tag)
        if (index < 0) {
            return
        }
        // 删除缓存视图
        _removeTagCache(tag)
        // 删除标签页
        tabs.value.splice(index, 1)
        // 当前路由被关闭，路由到下一个标签页
        if (isActiveTab(tag)) {
            const tab = index >= tabs.value.length ? tabs.value[tabs.value.length - 1] : tabs.value[index]
            _autoRouter(tab)
        }
    }

    /**
     * 关闭左侧菜单
     */
    const closeLeftTabs = (tag: RouteTag) => {
        // 保证至少一个标签页
        if (tabs.value.length <= 1) {
            return
        }
        // 获取标签位置
        const index = _index(tag)
        if (index < 0) {
            return
        }
        let currentClosed = false
        tabs.value = tabs.value.filter((item, i) => {
            if (i >= index || isAffixTab(item)) {
                return true
            }
            _removeTagCache(item)
            if (isActiveTab(item)) {
                currentClosed = true
            }
            return false
        })
        if (currentClosed) {
            _autoRouter(tag)
        }
    }

    /**
     * 关闭右侧菜单
     */
    const closeRightTabs = (tag: RouteTag) => {
        // 保证至少一个标签页
        if (tabs.value.length <= 1) {
            return
        }
        // 获取标签位置
        const index = _index(tag)
        if (index < 0) {
            return
        }
        let currentClosed = false
        tabs.value = tabs.value.filter((item, i) => {
            if (i <= index || isAffixTab(item)) {
                return true
            }
            _removeTagCache(item)
            if (isActiveTab(item)) {
                currentClosed = true
            }
            return false
        })
        if (currentClosed) {
            _autoRouter(tag)
        }
    }

    /**
     * 关闭其它菜单
     */
    const closeOtherTabs = (tag: RouteTag) => {
        // 保证至少一个标签页
        if (tabs.value.length <= 1) {
            return
        }
        // 获取标签位置
        const index = _index(tag)
        if (index < 0) {
            return
        }
        let currentClosed = false
        tabs.value = tabs.value.filter((item, i) => {
            if (i === index || isAffixTab(item)) {
                return true
            }
            _removeTagCache(item)
            if (isActiveTab(item)) {
                currentClosed = true
            }
            return false
        })
        if (currentClosed) {
            _autoRouter(tag)
        }
    }

    /**
     * 关闭全部菜单
     */
    const closeAllTabs = () => {
        // 保证至少一个标签页
        if (tabs.value.length <= 1) {
            return
        }
        const affixTabs = tabs.value.filter(item => isAffixTab(item))
        // 如果没有固定标签页，保留当前标签页
        if (isEmpty(affixTabs)) {
            const index = tabs.value.findIndex(item => item.fullPath == activeTab.value)
            if (index < 0) {
                return
            }
            tabs.value = tabs.value.filter((item, i) => {
                if (i === index) {
                    return true
                }
                _removeTagCache(item)
                return false
            })
        } else {
            tabs.value = affixTabs
            let currentExist = false
            const cachedNames: string[] = []
            tabs.value.forEach(item => {
                if (isActiveTab(item)) {
                    currentExist = true
                }
                if (item.cacheName) {
                    cachedNames.push(item.cacheName)
                }
            })
            cachedComponents.value = cachedNames
            // 当前标签页被关闭，导航到第一个固定标签页
            if (!currentExist) {
                _autoRouter(tabs.value[0])
            }
        }
    }

    /**
     * 添加当前路由至缓存
     */
    const addCacheQueue = (route: RouteLocationNormalizedGeneric) => {
        const name = route.meta.noCache === true ? undefined : (route.name as string)
        if (isEmpty(name)) {
            return
        }
        const cachedName = name as string
        if (!cachedComponents.value.includes(cachedName)) {
            cachedComponents.value.push(cachedName)
        }
    }

    /**
     * 清理指定标签页缓存
     */
    const _removeTagCache = (tag: RouteTag) => {
        _removeCache(tag.cacheName)
    }

    const removeCacheQueue = (route: RouteLocationNormalizedGeneric) => {
        const name = route.meta?.noCache === true ? undefined : (route.name as string)
        if (isEmpty(name)) {
            return
        }
        _removeCache(name as string)
    }

    const _removeCache = (name?: string) => {
        const index = isEmpty(name) ? -1 : cachedComponents.value.findIndex(v => v === name)
        if (index >= 0) {
            cachedComponents.value.splice(index, 1)
        }
    }

    const clearCacheQueue = () => {
        cachedComponents.value = []
    }

    const clear = () => {
        activeTab.value = ""
        tabs.value = []
        clearCacheQueue()
    }

    return {
        tabs,
        activeTab,
        cachedComponents,
        isActiveTab,
        isAffixTab,
        addTab,
        tabStatus,
        changeTab,
        addCacheQueue,
        removeCacheQueue,
        clearCacheQueue,
        clear,
        closeMethods: {
            closeTab,
            closeLeftTabs,
            closeRightTabs,
            closeOtherTabs,
            closeAllTabs
        }
    }
})
